package com.jishuo.nontax.bfc.service;

import com.github.pagehelper.PageHelper;
import com.jishuo.base.bean.BaseResult;
import com.jishuo.base.bean.ErrorCodeEnum;
import com.jishuo.base.bean.Pagination;
import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.service.SequenceService;
import com.jishuo.base.util.CommonUtil;
import com.jishuo.base.util.ExportSXSSFUtil;
import com.jishuo.base.util.GTimeUtil;
import com.jishuo.base.util.StringUtil;
import com.jishuo.nontax.bean.bank.OnlineOrder;
import com.jishuo.nontax.bean.bank.Student;
import com.jishuo.nontax.bean.message.SetStudent;
import com.jishuo.nontax.bean.message.SetStudentBackOut;
import com.jishuo.nontax.bean.vo.StudentVO;
import com.jishuo.nontax.bfc.dao.StudentMapper;
import com.jishuo.nontax.bfc.pzk.PzkService;
import com.jishuo.nontax.bfc.tlq.MessageFactory;
import com.jishuo.nontax.bfc.tlq.MessageService;
import com.jishuo.nontax.util.BillStateUtil;
import com.jishuo.nontax.util.PzkUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @auther dinggaofei
 * @Date 2022/12/22 10:55
 */
@Service
public class StudentService {
    private static Logger logger = LoggerFactory.getLogger(StudentService.class);
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private MessageService messageService;
    @Resource
    private NonTaxConfig nonTaxConfig;
    @Resource
    private OnlineOrderService onlineOrderService;
    @Resource
    private PzkService pzkService;

    @Resource
    private PzkUtils pzkUtils;

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 获得学生缴费列表
     *
     * @return
     */
    public List<StudentVO> listStudent(StudentVO studentVO, Pagination pagination) {
        // 当单页条数大于零时，启用分页
        if (pagination.getRows() > 0) PageHelper.startPage(pagination.getPage(), pagination.getRows());
        return this.studentMapper.selectStudentPage(studentVO);
    }

    /**
     * @param billNum 缴款码
     * @auther dinggaofei
     * @Date 2022/12/22 11:30
     * @description 向财政获取学生小条信息
     */
    public BaseResult getStudentVO(String billNum) {

        //从数据库查询学生缴费数据
        StudentVO bill = studentMapper.findStudentInfo(billNum);
        try {
            BaseResult result = new BaseResult();
            //已缴费直接返回
            if (bill != null && (bill.getBillstate() == 3 || bill.getIsbankaffirm() == 1)) {
                bill.setBillstate(3);
                result.setData(bill);
                result.setMsgExt(BillStateUtil.getBillState(BillStateUtil.BillType_Student, bill.getBillstate()));
                return result;
            }
            //更新messageid
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            if (bill == null) {
                long studentid = sequenceService.getNextSeq("FSSTUDENTSEQ");
                bill = new StudentVO();
                bill.setMessageid(messageid);
                bill.setStudentid(studentid);
                bill.setPayeraccount(billNum);
                studentMapper.insertBlankStudent(bill);
            } else {
                bill.setMessageid(messageid);
                studentMapper.updateMsgStudent(bill);
            }
            //从财政查询
            boolean suc = messageService.sendAndRecvMessage("GETSTUDENT", messageid, MessageFactory.getStudent(billNum), "2.0");
            if (suc) {
                bill = studentMapper.findStudentInfo(billNum);
//                Student student = bill.getStudent();
                result.setData(bill);
                result.setMsgExt(BillStateUtil.getBillState(BillStateUtil.BillType_Student, bill.getBillstate()));
                return result;
            }
            return new BaseResult(ErrorCodeEnum.BILL_GET_TIMEOUT);

        } catch (Exception e) {
            logger.info("获取学生小条失败，billnum=" + billNum, e);
            return new BaseResult(ErrorCodeEnum.SYS_ERR);
        }
    }

    /**
     * 从财政查询单据，返回xml
     * @param billNum 缴款码
     * @return
     */
    public BaseResult getStudent(String billNum) {
        BaseResult ret = this.getStudentVO(billNum);
        if (ret.isSuccess()) {
            try {
                //xml解析器
                Serializer serializer = new Persister();
                //xml转换器
                StringWriter sw = new StringWriter();
                Student student = ((StudentVO)ret.getData()).getStudent();
                serializer.write(student, sw);
                ret.setData(sw.toString());
            } catch (Exception e) {
                logger.info("获取学生小条失败，billnum=" + billNum, e);
                return new BaseResult(ErrorCodeEnum.SYS_ERR);
            }
        }
        return ret;
    }

    /**
     * @param billnum  票据号
     * @param paybankdt   交易时间
     * @param bankaffirm  流水号
     * @param bankstation 银行网点
     * @auther dinggaofei
     * @Date 2022/12/22 13:33
     * @description 获取学生缴费信息
     */
    public BaseResult setStudentPayInfo(String billnum, String paybankdt, String bankaffirm, String bankstation,String paychnl,String payeraccount) {
        // 参数检查
        String retMsg = "";
        if (billnum == null || "".equals(billnum)) {
            retMsg += "票号未填写；";
        } else if (paybankdt == null || "".equals(paybankdt)) {
            retMsg += "缴费时间未填写；";
        } else if (bankaffirm == null || "".equals(bankaffirm)) {
            retMsg += "交易流水号未填写；";
        }
        if (!"".equals(retMsg)) {
            logger.info("缴费参数错误。" + retMsg);
            return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        }

        StudentVO studentVo = studentMapper.findStudentInfo(billnum);
        //判断单据信息是否存在
        if (studentVo == null) {
            logger.info("单据缴款号不存在（票号：" + billnum + "）");
            return new BaseResult(ErrorCodeEnum.BILL_NOT_FOUND);
        }

        //判断是否已缴费
        if (studentVo.getIsbankaffirm() == 1) {
            // 日期一致的允许二次提交
            if (!paybankdt.substring(0, 10).equals(studentVo.getPaybankdt().substring(0, 10))) return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        } else if (studentVo.getBillstate() == 3) {
            return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        }
        //处理扩展业务

        studentVo.setPaybankdt(paybankdt);
        studentVo.setBankaffirm(bankaffirm);
        studentVo.setBankstation(bankstation);
        studentVo.setSendtime(sdf.format(new Date()));
        studentVo.setIsbankaffirm(1);
        studentVo.setHxbankaffirm(bankaffirm);
        int n = studentMapper.updateBillPay(studentVo);

        OnlineOrder oo = new OnlineOrder();
        oo.setBillnum(billnum);
        oo.setAmt(studentVo.getFunds().toPlainString());
        oo.setBankaffirm(bankaffirm);
        oo.setBilltype(2);
        oo.setPaybankdt(paybankdt);
        oo.setPaychnl(paychnl);
        oo.setPayee(studentVo.getAccountname());
        oo.setPayeeaccount(studentVo.getAccountcode());
        oo.setPayer(studentVo.getStudentname());
        oo.setPayeraccount(payeraccount);
        oo.setPaytype(1);
        onlineOrderService.saveOnlineOrder(oo);
        if (n < 1) {
            return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新学生缴费失败(" + billnum + ")");
        }

        //发送财政
        this.sendStudent(studentVo);
        // 写凭证
        pzkService.savePzmsg("SETSTUDENTPZK", pzkUtils.getStudent(studentVo));

        return new BaseResult();
    }

    /**
     * 财政返回票据，入库
     * @param data 财政报文
     * @param billstate 票据状态
     * @param sn 消息sn
     */
    public void setStudent(String data, int billstate, String sn) {

        if (billstate == 1) {

            //xml解析器
            Serializer serializer = new Persister();
            try {
                //返回学生缴费对象
                SetStudent student = serializer.read(SetStudent.class, new StringReader(data));
                if (student != null) {
                    StudentVO vo = new StudentVO(student);
                    vo.setBillstate(billstate);
                    vo.setIssend(2);
                    studentMapper.updateStudnet(vo);
                }
            } catch (Exception e) {
                logger.info("失败：" + e.toString(), e);
            }

        } else if (billstate > 1) {
            long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
            studentMapper.updateBillState(billstate, messageid);
        }
    }

    /** 导出 */
    public void studentExport(long bankid, String paybankdt, HttpServletResponse response) {
        if (bankid == 0 || StringUtil.isEmpty(paybankdt)) return;

        StudentVO vo = new StudentVO();
        vo.setBankid(bankid);
        vo.setPaybankdt(paybankdt);
        List<StudentVO> studentVOS = studentMapper.selectStudentPage(vo);
        String[] headers = {"学号", "流水号", "行政区划", "区划编码", "区划名称", "单位id", "单位（部门）编码", "单位（部门）名称", "班级", "姓名", "学号", "付款账号", "收款人银行id", "收款人银行名称", "收款人账户名称", "收款人账号", "金额", "银行划款日期", "银行网点", "银行交易流水号", "缴款方式", "单据状态", "发送时间", "__status", "银行核心交易流水号", "是否发送"};
        String[] col = {"studentid", "studnetnum", "cantonid", "cantoncode", "cantonname", "unitid", "unitcode", "unitname", "classname", "studentname", "payeeaccountcode", "payeeaccountcode", "bankid", "payeeaccountname", "payeeaccountcode", "payeebankname", "funds", "paybankdt", "bankstation", "bankaffirm", "payway", "billstate", "sendtime", "", "hxbankstation", "issend"};
        ExportSXSSFUtil ex = new ExportSXSSFUtil();
        SXSSFWorkbook workbook = ex.exportExcelSXSSF("学校缴费列表", headers, col, studentVOS, null);
        response.setContentType("application/vnd.ms-excel");
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    new String(("学校缴费列表.xls").getBytes(), "iso-8859-1"));
            OutputStream ouputStream = response.getOutputStream();
            workbook.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            logger.info("导出失败：" + e.toString(), e);
        }

    }

    /**
     * 根据票号发送单据
     * @param vo 票据
     * @return
     */
    private BaseResult sendStudent(StudentVO vo) {
        // 发送财政
        try {
            Object obj = MessageFactory.setStudentPayInfo(vo);
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETSTUDENTPAYINFO", messageid, obj, "2.0");
            return new BaseResult();
        } catch (Exception e) {
            logger.info("发送财政失败。" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
    }

    /** 页面，补发财政 */
    public BaseResult sendStudent(String billids) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<StudentVO> studentList = studentMapper.findStudentByIds(ids);
        for (StudentVO vo : studentList) {
            sendStudent(vo);
        }
        return new BaseResult();
    }

    /**
     * 冲销
     * @param billids ids
     * @param usercode 用户
     * @return
     */
    public BaseResult cleanStudent(String billids, String usercode) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<StudentVO> studentList = studentMapper.findStudentByIds(ids);

        Calendar cal = Calendar.getInstance();
        String cxTime = sdf.format(cal.getTime());
        cal.add(Calendar.MINUTE, 0 - nonTaxConfig.CxTime);
        String chkTime = sdf.format(cal.getTime());

        String errinfo = "";
        for (StudentVO studentVO : studentList) {
            if (studentVO.getSendtime() == null || studentVO.getSendtime().length() == 0 || chkTime.compareTo(studentVO.getSendtime()) < 0) {
                setStudentBackOut(cxTime, usercode, studentVO);
                studentMapper.updateIsbankAffirm(studentVO.getStudentid());
            } else {
                errinfo += studentVO.getStudentnum() + ",";
            }
        }
        if (!errinfo.equals("")) {
            errinfo += "超时冲销失败,其他单据冲销成功!";
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), errinfo);
        } else {
            errinfo = "冲销成功";
            return new BaseResult(ErrorCodeEnum.SUCCESS.getCode(), errinfo);
        }
    }

    /** 冲销 */
    private BaseResult setStudentBackOut(String backoutdt, String backoutname, StudentVO vo) {
        try {
            SetStudentBackOut student = new SetStudentBackOut();
            student.setStudentid(vo.getStudentid().toString());
            student.setCantonid(vo.getCantonid().toString());
            student.setUnitid(vo.getUnitid().toString());
            student.setStudentnum(vo.getStudentnum());
            student.setClassname(vo.getClassname());
            student.setStudentname(vo.getStudentname());
            student.setBankid(vo.getBankid().toString());
            student.setFund(vo.getFunds().toPlainString());
            student.setPayeraccount(vo.getPayeraccount());
            student.setPaybankdt(vo.getPaybankdt());
            student.setBankaffirm(vo.getBankaffirm());
            student.setBankstation(vo.getBankstation());
            student.setRemark("冲销");
            student.setBackoutname(backoutname);
            student.setBackoutdt(backoutdt);

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");

            messageService.sendMessage("SETSTUDENTBACKOUT", messageid, student, "2.0");
            // 写凭证
            pzkService.savePzmsgOut(BillStateUtil.BillType_Student, vo.getPayeraccount(), vo.getBankaffirm());

            return new BaseResult();
        } catch (Exception e) {
            logger.info("处理学校缴款失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }


    }

    /**
     * 学生缴费收款，页面提交
     * @param studentVO
     * @return
     */
    public BaseResult studentpayview(StudentVO studentVO) {
        try {
            String paybankdt = GTimeUtil.getDateTimeMark();
            BaseResult baseResult = setStudentPayInfo(studentVO.getPayeraccount(), paybankdt, studentVO.getBankaffirm(), studentVO.getBankstation(),"","");

            return baseResult;
        } catch (Exception e) {
            e.printStackTrace();
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }
}



